<?php

namespace app\common\model\banxi\say;

use app\common\enums\say\SayCategoryTypeEnum;
use app\common\enums\say\SayTeachSentenceStatusEnum;
use app\common\model\banxi\student\StudentCourse;
use app\common\model\common\BaseModel;
use think\db\exception\PDOException;
use think\Exception;
use think\exception\ValidateException;
use think\Model;
use think\model\concern\SoftDelete;

/**
 * 学员
 */
class SayTeachSentence extends BaseModel
{
    use SoftDelete;

    protected $name = 'banxi_say_teach_sentence';

    protected $autoWriteTimestamp = true;

    protected $deleteTime = 'del';

    protected $defaultSoftDelete = 0;

    protected $append = [
        'statusCn',
        'splitSentenceList',
        'sentenceWordColorList',
        'intonationGroupList',
        'coreVocabularyList',
        'expandVocabularyList',
        'answerList'
    ];

    protected $type = [
        'id' => 'string',
        'del' => 'string',
        'gradeId' => 'string',
        'courseExperience' => 'boolean',
        'createTime' => 'timestamp:Y-m-d H:i:s',
        'updateTime' => 'timestamp:Y-m-d H:i:s',
    ];

    //-----------------------------------------------------------------------------------
    //-                                    获取器                                      -
    //-----------------------------------------------------------------------------------

    public function getStatusCnAttr($value, $data): string
    {
        $value = $value ?: ($data['status'] ?? '');
        return (new SayTeachSentenceStatusEnum())->getDescription($value) ?? '';
    }

    public function getSplitSentenceListAttr($value, $data)
    {
        return isset($data['splitSentence']) ? json_decode($data['splitSentence'], true) : [];
    }

    public function getSentenceWordColorListAttr($value, $data)
    {
        $value = $value ?: ($data['sentenceWordColor'] ?? '');
        return json_decode($value, true) ?? [];
    }

    public function getIntonationGroupListAttr($value, $data)
    {
        $value = $value ?: ($data['intonationGroup'] ?? '');
        return json_decode($value, true) ?? [];
    }

    public function getCoreVocabularyListAttr($value, $data)
    {
        $value = $value ?: ($data['coreVocabulary'] ?? '');
        return json_decode($value, true) ?? [];
    }

    public function getExpandVocabularyListAttr($value, $data)
    {
        $value = $value ?: ($data['expandVocabulary'] ?? '');
        return json_decode($value, true) ?? [];
    }

    public function getAnswerListAttr($value, $data)
    {
        $value = $value ?: ($data['answer'] ?? '');
        return $value ? explode(',', $value) : [];
    }

    //-----------------------------------------------------------------------------------
    //-                                    处理方法                                      -
    //-----------------------------------------------------------------------------------

    //获取列表
    public function getListPage(array $where, string $page = '1', int $limit = 10): \think\Paginator
    {
        return self::with([
            'parentInfo' => function ($query) {
                $query->field('id,sentenceEn');
            },
            'gradeInfo' => function ($query) {
                $query->field('id,name');
            }])->hidden(['splitSentence', 'sentenceWordColor', 'intonationGroup', 'coreVocabulary', 'expandVocabulary', 'answer'])
            ->where($where)
            ->order([ 'sortNum' => 'asc'])
            ->paginate([
                'page' => $page,
                'list_rows' => $limit,
            ])->each(function ($item) {
                $item['parentId'] = (string)$item['parentId'];
            });

    }

    //获取列表(用于下拉选择)
    public function getListSelectPage(array $where, string $page = '1', int $limit = 10)
    {
        return self::where($where)
            ->order([ 'sortNum' => 'asc'])
            ->field('id,sentenceEn')
            ->paginate([
                'page' => $page,
                'list_rows' => $limit,
            ]);

    }

    //获取信息
    public function getInfo(array $where): array|Model|null
    {
        return $this->with([
            'parentInfo' => function ($query) {
                $query->field('id,sentenceEn');
            },
            'gradeInfo' => function ($query) {
                $query->field('id,name');
            }])
            ->where($where)->find();
    }

    /**
     * 新增/更新
     * @param $organizationId
     * @param $data
     * @param $dealUser
     * @return true
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function saveOrUpdate(array $data): bool
    {
        try {
            $id = $data['id'] ?? 0;
            $saveData = $data;
            $gradeInfo = SayGrade::where('id', $data['gradeId'])->find();
            if (empty($gradeInfo)) {
                throw new ValidateException('请选择年级');
            }
            $saveData['splitSentence'] = $saveData['splitSentenceList'] ? json_encode($data['splitSentenceList'], JSON_UNESCAPED_UNICODE) : '';
            $saveData['sentenceWordColor'] = $saveData['sentenceWordColorList'] ? json_encode($data['sentenceWordColorList'], JSON_UNESCAPED_UNICODE) : '';
            $saveData['intonationGroup'] = $saveData['intonationGroupList'] ? json_encode($data['intonationGroupList'], JSON_UNESCAPED_UNICODE) : '';
            $saveData['coreVocabulary'] = $saveData['coreVocabularyList'] ? json_encode($data['coreVocabularyList'], JSON_UNESCAPED_UNICODE) : '';
            $saveData['expandVocabulary'] = $saveData['expandVocabularyList'] ? json_encode($data['expandVocabularyList'], JSON_UNESCAPED_UNICODE) : '';
            $saveData['answer'] = implode(',', $data['answerList']);
            if (!$id) {
                $this->save($saveData);
            } else {
                $info = self::where('id', $id)->find();
                if (empty($info)) {
                    throw new ValidateException('课程不存在');
                }
                $info->save($saveData);
            }
        } catch (ValidateException|PDOException|Exception $e) {
            throw new ValidateException($e->getMessage());
        }
        return true;
    }

    public function del($ids)
    {
        try {
            $this->destroy(function ($query) use ($ids) {
                $query->whereIn('id', $ids);
            });
        } catch (PDOException|Exception $e) {
            throw new ValidateException($e->getMessage());
        }
        return true;
    }

    //拆分问题
    public function splitQuestion($question, $answer)
    {
        $parts = preg_split('/(#\{[\d\w]+\})/', $question, -1, PREG_SPLIT_DELIM_CAPTURE);
        $answer = explode(',', $answer);
        // 创建结果数组，将分隔符替换为 ___
        $result_array = [];
        $num = 0;
        foreach ($parts as $index => $part) {
            if ($index % 2 == 0) {
                // 内容部分，直接添加
                $result_array[] = [
                    'value' => $part,
                    'type' => 1
                ];
            } else {
                $result_array[] = [
                    'value' => $answer[$num] ?? '',
                    'type' => 2,
                ];
                $num++;
            }
        }
        return $result_array;
    }

    //获取其他句子的答案
    public function getOtherSentenceAnswer($id, $option)
    {
        $countOption = count($option);
        $maxOption = 4;
        $result = [];
        $answerList = [];
        $type = $countOption > 1 ? 2 : 1;
        foreach ($option as $item) {
            $result[] = [
                'value' => $item,
                'isCorrect' => 1,
            ];
            $answerList[] = [
                'value' => $item,
                'isCorrect' => 1,//是否正确答案 1是 0否
            ];
        }
        if ($countOption == $maxOption) {
            return $option;
        }
        $answer = $this->where([['id|parentId', '<>', $id]])->cache('SayTeachSentence:getOtherSentenceAnswer:' . $id, 60 * 5)->column('answer');
        $answers = [];
        foreach ($answer as $item) {
            $answers = array_merge($answers, explode(',', $item));
        }
        $answers = array_unique($answers);
        foreach ($answers as $answer) {
            if (!in_array($answer, $option)) {
                $result[] = [
                    'value' => $answer,
                    'isCorrect' => 0,//是否正确答案 1是 0否
                ];
            }
            if (count($result) == $maxOption) {
                break;
            }
        }
        shuffle($result);
        return [
            'type' => $type,
            'option' => $result,
            'answer' => $answerList
        ];
    }

    //获取其他句子的图片
    public function getOtherSentenceImage($id, $sentenceImage)
    {
        $maxOption = 8;
        $result = [
            [
                'value' => $sentenceImage,
                'isCorrect' => 1,
            ]];
        $option = $this->where([['id|parentId', '=', $id]])->cache('SayTeachSentence:getOtherSentenceImage:' . $id, 60 * 5)->column('sentenceImage');
        foreach ($option as $item) {
            if ($item != $sentenceImage) {
                $result[] = [
                    'value' => $item,
                    'isCorrect' => 0,
                ];
            }
            if (count($result) == $maxOption) {
                break;
            }
        }
        shuffle($result);
        return $result;

    }

    public function getListStudentPage(string $studentId, array $where, string $page = "1", int $limit = 10)
    {
        $studentCourse = new StudentCourse();
        $courseIds = $studentCourse->listByStudentId($studentId);
        $where[] = ['id', 'not in', $courseIds];
        return $this->listEntityPage($where, false, $page, $limit);
    }

    public function getListStudentOpenPage(bool $isPractice, string $studentId, array $where, string $page = "1", int $limit = 10)
    {
        if (!$isPractice) {
            $studentCourse = new StudentCourse();
            $courseIds = $studentCourse->listByStudentId($studentId);
            if (empty($courseIds)) {
                $where[] = ['id', '=', 0];
            } else {
                $where[] = ['id', 'in', $courseIds];
            }
        }
        return $this->listEntityPage($where, $isPractice, $page, $limit);
    }

    public function listEntityPage(array $where, $isPractice, string $page = "1", int $limit = 10)
    {
        return $this->alias('a')->with([
            'gradeInfo' => function ($query) {
                $query->field('id,name');
            }])
            ->hidden(['splitSentence', 'sentenceWordColor', 'intonationGroup', 'coreVocabulary', 'expandVocabulary', 'answer'])
            ->where($where)->whereExists(function ($query) use ($isPractice) {
                $query->name('banxi_say_grade')
                    ->alias('b')
                    ->whereColumn('id', '=', 'a.gradeId')
                    ->where('del', 0)
                    ->whereExists(function ($query) use ($isPractice) {
                        $subquery = $query->name('banxi_say_category')
                            ->whereColumn('id', '=', 'b.sayCategoryId')
                            ->where('del', 0);
                        if ($isPractice) {
                            $subquery->where('type', '=', SayCategoryTypeEnum::E3);
                        } else {
                            $subquery->where('type', '=', SayCategoryTypeEnum::E1);
                        }

                    });
            })->paginate(['page' => $page, 'list_rows' => $limit])->each(function ($item) use ($isPractice) {
                $item['courseExperience'] = $isPractice;
            });
    }

    //-----------------------------------------------------------------------------------
    //-                                    模型关联                                      -
    //-----------------------------------------------------------------------------------
    public
    function gradeInfo()
    {
        return $this->hasOne(SayGrade::class, 'id', 'gradeId');
    }

    public
    function parentInfo()
    {
        return $this->hasOne(SayTeachSentence::class, 'id', 'parentId');
    }

    public
    function childrenList()
    {
        return $this->hasMany(SayTeachSentence::class, 'parentId', 'id');
    }


}